package speed2010.andreza.vspeed.util;

/**
 * @author <a href="mailto:andreza.lba@gmail.com">Andreza Leite de Alencar</a>
 */
public final class StringUtils {

	private StringUtils() {
	}

	private static byte[] _base64ToBytes(final String s) {
		int len = 0;
		for (int i = 0; i < s.length(); i++) {
			if (s.charAt(i) != '=') {
				len++;
			}
		}

		final int digit[] = new int[len];
		for (int i = 0; i < len; i++) {
			final char c = s.charAt(i);
			if ((c >= 'A') && (c <= 'Z')) {
				digit[i] = c - 65;
			} else if ((c >= 'a') && (c <= 'z')) {
				digit[i] = (c - 97) + 26;
			} else if ((c >= '0') && (c <= '9')) {
				digit[i] = (c - 48) + 52;
			} else if (c == '+') {
				digit[i] = 62;
			} else if (c == '/') {
				digit[i] = 63;
			}
		}

		final byte b[] = new byte[len - 1];
		switch (len) {
			case 4 : // '\004'
				b[2] = (byte) (((digit[2] & 3) << 6) | digit[3]);
				// fall through

			case 3 : // '\003'
				b[1] = (byte) (((digit[1] & 15) << 4) | ((digit[2] & 60) >>> 2));
				// fall through

			case 2 : // '\002'
				b[0] = (byte) ((digit[0] << 2) | ((digit[1] & 48) >>> 4));
				// fall through

			default :
				return b;
		}
	}

	private static char _base64Digit(final int i) {
		if (i < 26) {
			return (char) (65 + i);
		}
		if (i < 52) {
			return (char) (97 + (i - 26));
		}
		if (i < 62) {
			return (char) (48 + (i - 52));
		}
		return i != 62 ? '/' : '+';
	}

	public static byte[] base64StringToByteArray(final String s) throws NumberFormatException {
		String t = "";
		for (int i = 0; i < s.length(); i++) {
			final char c = s.charAt(i);
			if (c == '\n') {
				continue;
			}
			if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || (c == '+')
					|| (c == '/')) {
				t = (new StringBuilder(String.valueOf(t))).append(c).toString();
				continue;
			}
			if (c != '=') {
				throw new NumberFormatException();
			}
			break;
		}

		int len = t.length();
		int n = 3 * (len / 4);
		switch (len % 4) {
			case 1 : // '\001'
				throw new NumberFormatException();

			case 2 : // '\002'
				len += 2;
				n++;
				t = (new StringBuilder(String.valueOf(t))).append("==").toString();
				break;

			case 3 : // '\003'
				len++;
				n += 2;
				t = (new StringBuilder(String.valueOf(t))).append("=").toString();
				break;
		}
		final byte b[] = new byte[n];
		for (int i = 0; i < (len / 4); i++) {
			final byte temp[] = _base64ToBytes(t.substring(4 * i, 4 * (i + 1)));
			for (int j = 0; j < temp.length; j++) {
				b[(3 * i) + j] = temp[j];
			}

		}

		return b;
	}

	public static String byteArrayToBase64String(final byte b[]) {
		return byteArrayToBase64String(b, b.length);
	}

	public static String byteArrayToBase64String(final byte b[], int len) {
		String s = "";
		int n = len / 3;
		int m = len % 3;
		for (int i = 0; i < n; i++) {
			final int j = i * 3;
			s = (new StringBuilder(String.valueOf(s))).append(toBase64(b[j], b[j + 1], b[j + 2])).toString();
		}

		if (m == 1) {
			s = (new StringBuilder(String.valueOf(s))).append(toBase64(b[len - 1])).toString();
		} else if (m == 2) {
			s = (new StringBuilder(String.valueOf(s))).append(toBase64(b[len - 2], b[len - 1])).toString();
		}
		String result = "";
		len = s.length();
		n = len / 64;
		m = len % 64;
		for (int i = 0; i < n; i++) {
			result = (new StringBuilder(String.valueOf(result))).append(s.substring(i * 64, (i + 1) * 64)).toString();
		}

		if (m > 0) {
			result = (new StringBuilder(String.valueOf(result))).append(s.substring(n * 64, len)).toString();
		}
		return result;
	}

	public static String byteArrayToHexString(final byte b[]) {
		String result = "";
		for (final byte element : b) {
			result = (new StringBuilder(String.valueOf(result))).append(byteToHexString(element)).toString();
		}

		return result;
	}

	public static String byteToHexString(final byte b) {
		final String hexDigits = "0123456789abcdef";
		int n = b;
		if (n < 0) {
			n += 256;
		}
		return "" + hexDigits.charAt(n / 16) + hexDigits.charAt(n % 16);
	}

	private static String toBase64(final byte b1) {
		final int digit[] = new int[2];
		digit[0] = (b1 & 252) >>> 2;
		digit[1] = (b1 & 3) << 4;
		String result = "";
		for (final int element : digit) {
			result = (new StringBuilder(String.valueOf(result))).append(_base64Digit(element)).toString();
		}

		result = (new StringBuilder(String.valueOf(result))).append("==").toString();
		return result;
	}

	private static String toBase64(final byte b1, final byte b2) {
		final int digit[] = new int[3];
		digit[0] = (b1 & 252) >>> 2;
		digit[1] = (b1 & 3) << 4;
		digit[1] |= (b2 & 240) >> 4;
		digit[2] = (b2 & 15) << 2;
		String result = "";
		for (final int element : digit) {
			result = (new StringBuilder(String.valueOf(result))).append(_base64Digit(element)).toString();
		}

		result = (new StringBuilder(String.valueOf(result))).append("=").toString();
		return result;
	}

	private static String toBase64(final byte b1, final byte b2, final byte b3) {
		final int digit[] = new int[4];
		digit[0] = (b1 & 252) >>> 2;
		digit[1] = (b1 & 3) << 4;
		digit[1] |= (b2 & 240) >> 4;
		digit[2] = (b2 & 15) << 2;
		digit[2] |= (b3 & 192) >> 6;
		digit[3] = b3 & 63;
		String result = "";
		for (final int element : digit) {
			result = (new StringBuilder(String.valueOf(result))).append(_base64Digit(element)).toString();
		}

		return result;
	}

	/*
	 * Codigo Relativo a Remocao dos Acentos de Strings:
	 */

	private static String caracteresAcentuados = "Ã§Ã‡Ã¡Ã©Ã­Ã³ÃºÃ½Ã�Ã‰Ã�Ã“ÃšÃ�Ã Ã¨Ã¬Ã²Ã¹Ã€ÃˆÃŒÃ’Ã™Ã£ÃµÃ±Ã¤Ã«Ã¯Ã¶Ã¼Ã¿Ã„Ã‹Ã�Ã–ÃœÃƒÃ•Ã‘Ã¢ÃªÃ®Ã´Ã»Ã‚ÃŠÃŽÃ”Ã›";
	private static String caracteresNaoAcentuados = "cCaeiouyAEIOUYaeiouAEIOUaonaeiouyAEIOUAONaeiouAEIOU";
	private static char[] tabelaCaracteres;

	static {
		tabelaCaracteres = new char[256];

		for (int i = 0; i < tabelaCaracteres.length; ++i) {
			tabelaCaracteres[i] = (char) i;
		}
		for (int i = 0; i < caracteresAcentuados.length(); ++i) {
			tabelaCaracteres[caracteresAcentuados.charAt(i)] = caracteresNaoAcentuados.charAt(i);
		}
	}

	public static String removerAcentos(final String stringAcentuada) {
		final StringBuilder stringNaoAcentuada = new StringBuilder();

		for (int i = 0; i < stringAcentuada.length(); i++) {
			final char c = stringAcentuada.charAt(i);
			if (c < 256) {
				stringNaoAcentuada.append(tabelaCaracteres[c]);
			} else {
				stringNaoAcentuada.append(c);
			}
		}

		return stringNaoAcentuada.toString();
	}

	public static String toCamelCase(final boolean pEspecial, final String pNome) {
		String vNmColuna = pNome;
		String vSubstringResto = vNmColuna.substring(1, vNmColuna.length());
		if (!pEspecial) {
			vSubstringResto = vSubstringResto.toLowerCase();
		}
		vNmColuna = vNmColuna.substring(0, 1).toUpperCase() + vSubstringResto;
		int vIndex = vNmColuna.indexOf("_");
		while (vIndex > 0) {
			try {
				vNmColuna = vNmColuna.substring(0, vIndex) + vNmColuna.substring(vIndex + 1, vIndex + 2).toUpperCase()
						+ vNmColuna.substring(vIndex + 2);
				vIndex = vNmColuna.indexOf("_");
			} catch (final Exception e) {
				vIndex = -1;
			}
		}
		return vNmColuna;
	}

	public static String escapeHTML(final String pInput) {
		if (pInput == null) {
			return null;
		}
		return pInput.replaceAll("<", "&#60;").replaceAll(">", "&#62;").replaceAll("\"", "&#34;")
				.replaceAll("&", "&#38;");
	}

	public static String convertToUnicode(final String str) {
		final StringBuffer ostr = new StringBuffer();
		for (int i = 0; i < str.length(); i++) {
			final char ch = str.charAt(i);

			if ((ch >= 0x0020) && (ch <= 0x007e)) {
				ostr.append(ch);
			} else {
				ostr.append("\\u");
				final String hex = Integer.toHexString(str.charAt(i) & 0xFFFF);
				for (int j = 0; j < (4 - hex.length()); j++) {
					ostr.append("0");
				}
				ostr.append(hex.toLowerCase());
			}
		}

		return ostr.toString();
	}
}